//
// Created by 抑~风 on 2022/12/10.
//

#include "semantic_analysis.h"

namespace CWJ {
    namespace SEMA_ANALYSIS {


        Scanner::AnnotatedTreePtr RefResolver::visit(Scanner::AnnotatedTreePtr tree) {
            this->at = tree;
            this->visit(tree->getTree());
            return this->at;
        }

        void RefResolver::visitExpression(ResASTNodePtr node){
            if(node->getNodeType() == NodeType::TOKEN){
                Variable* var = nullptr;
                if(node->getContext() == "IDENTIFIER"){
                    var = this->at->lookupVar(node,node->getVal());
                    if(!var)    throw runtime_error("RefResolver::visitExpression : var not define");
                    this->at->addSymbolOfNode(node,var);
                }else if(node->getContext() == "DECIMALLITERAL"){
//                    auto literal = new Literal(this->at->getScopeOfNode(node),node,&CWJType::intType,node->getVal());
                    int val = stoi(node->getVal());
                    var = new Variable("literal",this->at->getScopeOfNode(node),node,&CWJType::intType,val,true);
                    this->at->addSymbolOfNode(node,var);
                }
            }

            for(const auto& s : node->getChilds() ){
                this->visitExpression(s);
            }

        }




        void RefResolver::visit(Scanner::ResASTNodePtr node) {
            if(!node)   return ;
            if(node->getNodeType() == NodeType::TOKEN)  return;
            const auto& ct = node->getContext();

            for(const auto& s : node->getChilds()){
                this->visit(s);
            }

            if(ct == "assginExpression"){
                // 赋值表达式的树代表一个变量，执行就就执行其expression对变量进行修改
                string ident;
                this->at->getIdent(node,ident);
                Variable* var = this->at->lookupVar(node,ident);
                if(!var)    throw runtime_error("RefResolver::visit :assginExpression has var which not defined" );

                this->at->addSymbolOfNode(node,var);
            }else if(ct == "expression"){
                this->visitExpression(node);
                return ;
            }else if(ct == "functionCall"){

                string ident;
                this->at->getIdent(node,ident);
                vector<CWJType*>list;
                Symbol*  func = this->at->lookupFunction(node,ident,list);

                if(ident == FunctionType::PRINT.getName()){
                    func = &FunctionType::PRINT;
                }else if( ident == FunctionType::PRINTLN.getName()){
                    func = &FunctionType::PRINTLN;
                }
                else if(!func)   {
                    throw runtime_error("RefResolver::visit :function not defined" );
                }
                this->at->addSymbolOfNode(node,func);
            }else if(ct == "dotExpression"){

            }

        }


    }
}